/*
 * Author: Karthic Kumar Sekar [A0092622]
 */
package sg.edu.nus.iss.team4ft.ui;

import java.awt.BorderLayout;
import java.awt.Checkbox;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.event.ItemEvent;
import java.util.Date;

import sg.edu.nus.iss.team4ft.exception.InvalidOperationException;
import sg.edu.nus.iss.team4ft.service.CallService;
import sg.edu.nus.iss.team4ft.service.CallTransfer;
import sg.edu.nus.iss.team4ft.service.Channel;
import sg.edu.nus.iss.team4ft.service.DataService;
import sg.edu.nus.iss.team4ft.service.Feature;
import sg.edu.nus.iss.team4ft.service.FeatureCode;
import sg.edu.nus.iss.team4ft.util.AppConstant;
import sg.edu.nus.iss.team4ft.util.DateUtil;


public class FeatureControl extends Panel {

	private static final long serialVersionUID = 1L;

	private Checkbox cbFeature = new Checkbox();
	private DateControl dateControl;	
	private Label dateText = new Label() ;
	private Label errorText = new Label();
	private PlanControl planControl = null;
	
	private boolean isDefaultService = false;
	private boolean isFeatureSelected = false;		
			
	private Feature actualFeature;
	private Feature modifiedFeature;
	private FeatureCode featureCode;
	private Mode mode;
		
	private CheckboxTestListener cbFeatureListener = new CheckboxTestListener(){
		public void itemStateChanged(ItemEvent arg0){
			toggleVisibility();
		}
	};
	
	public FeatureControl(FeatureCode featureCode, Mode mode, PlanControl planControl) {		
		initControls(featureCode, mode, planControl, "");						
	}
	
	public FeatureControl(FeatureCode featureCode, Mode mode, String channelName, PlanControl planControl) {
		initControls(featureCode, mode, planControl,channelName);						
	}
	
	public FeatureControl(Feature feature, Mode mode, PlanControl planControl) {		
		isFeatureSelected = true;		
		//If the feature was deactivated, do not show it in the edit mode. 
		//Because, the feature is maintained only for history.		
		//So the user can activate it as a new feature.
		if(feature != null && feature.getEndDate() == null)
			this.setFeature(feature);
		
		initControls(feature.getFeatureCode(), mode, planControl, feature.getServiceName());					
	}

	private void initControls(FeatureCode featureCode, Mode mode, PlanControl planControl, String featureName) {
		this.planControl = planControl;
		this.setFeatureCode(featureCode);
		if(featureName == "")
			featureName = getFeatureName();
		this.cbFeature.setLabel(featureName);
		this.setFeatureCode(featureCode);
		this.loadControlValues(mode);
		this.setMode(mode);
		toggleVisibility();
	}

	public FeatureCode getFeatureCode() {
		return featureCode;
	}

	public void setFeatureCode(FeatureCode featureCode) {
		this.featureCode = featureCode;
		
		if(featureCode == FeatureCode.LocalCall )
			isDefaultService = true;		
		for (String s : AppConstant.DEFAULT_CHANNEL_NAMES) {
			if(this.cbFeature.getLabel().equals(s))
				isDefaultService = true;
		}
			
	}

	public void setFeature(Feature modifiedFeature) {
		this.modifiedFeature = modifiedFeature;
		this.setActualFeature(modifiedFeature);
	}

	public Feature getActualFeature() {
		return actualFeature;
	}

	private void setActualFeature(Feature actualFeature) {
		this.actualFeature = actualFeature;
	}
	
	public void setMode(Mode mode) {
		this.mode = mode;
		this.dateControl.setMode(mode);
		
		if(this.mode == Mode.New)
			 modeNew();
		else if(this.mode == Mode.Edit)
			 modeEdit();
		else if(this.mode == Mode.View)
			 modeView();
	}
	
	public void changeStateOnParentSelected(boolean isParentSelected){
		if(isDefaultService)
			this.cbFeature.setState(isParentSelected);
		if(!isParentSelected)
			this.cbFeature.setState(isParentSelected);
	}

	public Feature getFeature(Date date) throws Exception {
		try{
			//if default service (eg: local call) the feature will be created in the plan itself.
			//so return null at this point
			if(isDefaultService)
				return null;
				
			if(date == null)
				date = this.dateControl.getDate();		
			
			if(this.modifiedFeature == null){
				if(this.cbFeature.getState())
					InitFeature();
			}
			else{
				if(this.cbFeature.getState() && date != null)
					this.modifiedFeature.setStartDate(date);
				if(!this.cbFeature.getState())
					this.modifiedFeature.setEndDate(date);
			}
				
			return modifiedFeature;
		}catch (Exception e) {
			errorNotification();
			throw e;
		}
	}

	private void errorNotification() {
		this.setBackground(Color.RED);
		this.invalidate();
		this.validate();
		this.repaint();
	}
	
	public boolean isValidToSave() throws Exception{
		try{
		if(isDefaultService)
			return true;
		if(dateControl.isValid())
		{
			if(isFeatureSelected && mode == Mode.Edit && !this.cbFeature.getState())
				if(DateUtil.dateIsBefore(this.dateControl.getDate(), this.modifiedFeature.getStartDate()))
					throw new InvalidOperationException(this.cbFeature.getLabel() + AppConstant.DEACTIVATION_DATE_MSG_START + DateUtil.defaultFormat(this.dateControl.getDate()) + 
							AppConstant.ACTIVATION_DATE_MSG + DateUtil.defaultFormat(this.modifiedFeature.getStartDate()) + "].");
			

			if(!isFeatureSelected && mode == Mode.New && this.cbFeature.getState())
				if(DateUtil.dateIsBefore(this.dateControl.getDate(), DateUtil.getDate()))
					throw new InvalidOperationException(this.cbFeature.getLabel() + AppConstant.ACTIVATION_DATE_MSG_START + DateUtil.defaultFormat(this.dateControl.getDate()) 
							+ AppConstant.CURRENT_DATE_MSG);
			
			return true;
		}
		return false;
		}catch (Exception e) {
			errorNotification();
			throw e;
		}
	}
	
	@Override
	public void setEnabled(boolean b) {
		if(!isDefaultService){
			this.cbFeature.setEnabled(b);
			this.dateControl.setEnabled(false);
		}
	}
	
	private void loadControlValues(Mode mode) {
		this.setPreferredSize(new java.awt.Dimension(300, 30));
		this.cbFeature.setPreferredSize(new java.awt.Dimension(100, 20));
		this.setLayout(new BorderLayout(0,1));
		
		Panel row1 = new Panel(new FlowLayout(FlowLayout.LEFT));
		this.cbFeature.addItemListener(cbFeatureListener);
		row1.add(this.cbFeature);
		dateText.setFont(new java.awt.Font("Arial",2,10));

		if(modifiedFeature == null || mode == Mode.New)
			this.dateControl = new DateControl(AppConstant.ACTIVATE, mode);
		else if(modifiedFeature != null){
			dateText.setText("[" + AppConstant.ACTIVATE + DateUtil.defaultFormat(modifiedFeature.getStartDate()) +"]");
			if( mode == Mode.Edit)
				this.dateControl = new DateControl(AppConstant.DEACTIVATE, mode);
		}
		
		this.errorText.setForeground(Color.RED);
		this.errorText.setText(AppConstant.ERROR_TERMINATION);
		this.errorText.setVisible(true);		

		this.add("West", row1);
		this.add("Center", dateControl);
		this.add("East", dateText);
	}
	
	private void modeNew(){
		//If the feature is a default service for the plan, disable it by default
		if(isDefaultService){
			this.cbFeature.setEnabled(false);
			this.dateControl.setVisible(false);
		}
		else{
			this.dateControl.setVisible(true);
			this.dateControl.setText(AppConstant.ACTIVATE);
			this.dateControl.setEnabled(false);
			this.cbFeature.setEnabled(true);
		}
	}
	
	private void modeEdit(){
		if(isDefaultService){
			if(this.modifiedFeature != null && this.modifiedFeature.getPlan()!= null && this.modifiedFeature.getPlan().getEndDate() != null)
				this.cbFeature.setState(true);
			this.cbFeature.setEnabled(false);
			this.dateControl.setVisible(false);
		}
		else
		{
			this.dateText.setVisible(true);
			this.dateControl.setEnabled(false);
		}

		if(isFeatureSelected){			
			if(this.modifiedFeature.getEndDate() == null){
				this.cbFeature.setState(true);
				if(!isDefaultService){
					this.dateText.setText("[" + AppConstant.ACTIVATE + DateUtil.defaultFormat(this.modifiedFeature.getStartDate()) + "]");
					this.dateText.setVisible(true);
				}
				this.dateControl.setText(AppConstant.DEACTIVATE);
				this.dateControl.setEnabled(false);
			}
			else{
				modeNew();
			}
		}
	}
	
	private void modeView(){		
		this.cbFeature.setEnabled(false);
		this.dateControl.setVisible(false);

		if(isFeatureSelected){		
			String showDate = AppConstant.ACTIVATE + DateUtil.defaultFormat(this.modifiedFeature.getStartDate());
			boolean state = true;

			if(this.modifiedFeature.getEndDate() == null)
			{
				showDate = AppConstant.DEACTIVATE + DateUtil.defaultFormat(this.modifiedFeature.getEndDate());
				state = false;
			}
			
			this.cbFeature.setState(state);	
			this.dateText.setVisible(true);
			this.dateText.setText("[" + showDate + "]");
		}
	}
	
	private void toggleVisibility(){
		boolean isEnabled = this.cbFeature.getState();
		
		if(mode == Mode.Edit && isFeatureSelected)
			isEnabled = !isEnabled;
		
		if(!isDefaultService){
			this.dateControl.setEnabled(isEnabled);
		}	
	}
	
	private void InitFeature() throws Exception{
		try{
			if(modifiedFeature == null){
				switch(featureCode){
				case LocalCall:
				case InternationalCall:
				case RoamingCall:
					modifiedFeature = new CallService(this.dateControl.getDate(), featureCode, planControl.getActualPlan());
					break;
				case CallTransfer:
					modifiedFeature = new CallTransfer(this.dateControl.getDate(), planControl.getActualPlan());
					break;
				case DataService:
					modifiedFeature = new DataService(this.dateControl.getDate(), planControl.getActualPlan());
					break;
				case ChannelService:
					modifiedFeature = new Channel(this.cbFeature.getLabel(),this.dateControl.getDate(), planControl.getActualPlan());
					break;
				}
			}
		}catch (Exception e) {
			errorNotification();
			throw e;
		}
	}
	
	private String getFeatureName(){
		switch(featureCode){
		case LocalCall:
			return AppConstant.LOCAL_CALL_FEATURE;
		case InternationalCall:
			return AppConstant.INTERNATIONAL_CALL_FEATURE;
		case RoamingCall:
			return AppConstant.ROAMING_CALL_FEATURE;
		case CallTransfer:
			return AppConstant.CALL_TRANSFER_FEATURE;
		case DataService:
			return AppConstant.DATA_SERVICE_FEATURE;
		case ChannelService:
			return AppConstant.CHANNEL_FEATURE;
		default:
			return "";
		}
	}
}
